using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using AutoMapper;
using Crossborder.Common.Utility;
using Crossborder.Common.Utility.Encrypt;
using Crossborder.Common.Utility.HttpHelper;
using Crossborder.Core;
using Crossborder.Core.Dto;
using Crossborder.Core.Repository;
using Crossborder.Domian;
using Crossborder.Domian.Users;
using Crossborder.IService;
using Microsoft.IdentityModel.Tokens;

namespace Crossborder.Service.Users
{
    public partial class UserService : IUserService
    {
        private CrossborderDbContext _Context { get; set; }

        public IRepository<User> _UserRep { get; set; }

        public IRepository<UserPassword> _PwdRep { get; set; }

        public IMapper _Map { get; set; }

        public UserService(IRepository<User> userRep,
        IRepository<UserPassword> pwdRep,
        IMapper map,
        CrossborderDbContext context)
        {
            _UserRep = userRep;
            _PwdRep = pwdRep;
            _Context = context;
            _Map = map;
        }

        public async Task<List<UserDto>> QueryUser(UserDto dto)
        {
            var sql = "select Id,UserId,UserName,NickName,Role,Email,CreateDate,ModifyDate,IsEnabled,IsDelete from [dbo].[User]";
            var info = await _UserRep.QueryAsync(sql, dto);
            var list = _Map.Map<List<UserDto>>(info);
            return list;
        }

        public async Task<HttpResponsion> GetUser(string? userId)
        {
            if (string.IsNullOrWhiteSpace(userId))
            {
                return HttpHelper.Fail("查询出错！");
            }
            List<string> str = new();
            var info = await _UserRep.GetAsync(o => o.UserId == userId && o.IsDelete == false && o.IsEnabled == true);
            var result = _Map.Map<UserDto>(info);
            result.realName = info.UserName;
            str.Add(info.Role ?? "User");
            result.roles = str;
            return HttpHelper.Success(result);
        }

        public async Task<HttpResponsion> CreateUser(UserInputDto dto)
        {
            var user = _Map.Map<User>(dto);
            user.Create();
            var result = _UserRep.Insert(user);
            if (result != null)
            {
                var IsSuccess = await CreatePassword(result.UserId, dto.Password);
                if (!IsSuccess)
                {
                    _Context.Attach(user);
                    _Context.Update(user).Property(m => m.IsEnabled == false && m.IsDelete == true);
                    await _Context.SaveChangesAsync();
                    return HttpHelper.Fail("用户创建失败");
                }
                return HttpHelper.Success(result);
            }
            else
            {
                return HttpHelper.Fail("用户创建失败");
            }

        }

        public async Task<HttpResponsion> Login(LoginInputDto dto)
        {
            var user = await _UserRep.GetAsync(o => o.UserName == dto.UserName && o.IsEnabled == true && o.IsDelete == false);
            if (user == null)
            {
                return HttpHelper.Fail("用户不存在！");
            }
            var encryptPwd = MD5Helper.MD5EncryptFor32(dto.Password);
            var pwd = await _PwdRep.GetAsync(o => o.UserId == user.UserId && o.Password == encryptPwd && o.IsEnabled == true && o.IsDelete == false);
            if (pwd == null)
            {
                return HttpHelper.Fail("用户密码错误");
            }
            GetToken(user, out UserDto result);
            return HttpHelper.Success(result);
        }

        private void GetToken(User user, out UserDto dto)
        {
            var tokenModel = Appsettings.app<JwtTokenModel>("Jwt");
            var claims = new Claim[]
            {
                new Claim(ClaimTypes.Name, user.NickName),
                new Claim("UserId", user.UserId),
                new Claim(ClaimTypes.Role, user.Role)
            };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenModel.Security));

            var token = new JwtSecurityToken(
                issuer: tokenModel.Issuer,
                audience: tokenModel.Audience,
                claims: claims,
                notBefore: DateTime.Now,
                expires: DateTime.Now.AddHours(tokenModel.Expires),
                signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
            );
            var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
            dto = _Map.Map<UserDto>(user);
            dto.accessToken = jwtToken;
        }
    }
}